#include <stdio.h>
#include "jeu.h"
#include "personnage.h"
#include "terrain.h"
#include "constante.h"
#include "ennemi.h"
#include "time.h"
#include "portail.h"

void jeuInit(Jeu *pJeu)
{
    FILE *monFic =NULL;

    int i ;
    int valret;

    float xinit, yinit;

    monFic=fopen("src/ennemi.txt","r");
    if(monFic==NULL)
    {
        printf(" Erreur lors de l'ouverture du fichier ennemi \n");
    }

    valret=fscanf(monFic,"%d\n",&(pJeu->nbEnnemis));

    pJeu->tabEnnemis = malloc(pJeu->nbEnnemis*sizeof(Ennemi));

    for(i=0; i<pJeu->nbEnnemis; i++)
    {
        valret=fscanf(monFic,"%f:%f:%f\n",&xinit,&yinit,&(pJeu->tabEnnemis[i].intervalle));

        if(valret!=3)
        {
            printf("Erreur de Lecture du fichier terrain pour l'initialisation de tabEnnemis[%d] \n", i);
        }

        ennemiInit(&(pJeu->tabEnnemis[i]),xinit,yinit);
    }

    portailInit(&(pJeu->tabPortails[0]), 16.0 , 15.0);
    portailInit(&(pJeu->tabPortails[1]), 56.0 , 15.0);

    personnageInit(&(pJeu->personnage), 10.0, 0.0);

    terrainInit(&(pJeu->terrain), "src/terrain.txt");

    fclose(monFic);
}


void jeuTestament(Jeu *pJeu)
{
    personnageDetruire(&(pJeu->personnage));

    terrainLibere(&(pJeu->terrain));

	free(pJeu->tabEnnemis);

    pJeu->nbEnnemis=0;
}


int jeuGetNbEnnemis(const Jeu *pJeu)
{
    return pJeu->nbEnnemis;
}

void jeuSetNbEnnemis(Jeu *pJeu, int i)
{
    pJeu->nbEnnemis = i;
}


const Terrain * jeuGetConstTerrain(const Jeu *pJeu)
{
    return &(pJeu->terrain);
}
const Personnage * jeuGetConstPersonnage(const Jeu *pJeu)
{
    return &(pJeu->personnage);
}

const Ennemi * jeuGetConstEnnemi(const Jeu *pJeu, int i)
{
    return &(pJeu->tabEnnemis[i]);
}

const Portail * jeuGetConstPortail(const Jeu *pJeu, int i)
{
    return (&(pJeu->tabPortails[i]));
}


void jeuPersoGravite(Jeu *pJeu)
{
    if(terrainPositionValide(&(pJeu->terrain) ,
                             (int)personnageGetPosX(&(pJeu->personnage)),
                             (int)(personnageGetPosY(&(pJeu->personnage)) + 1))
            &&
            terrainPositionValide(&(pJeu->terrain) ,
                                  (int)(personnageGetPosX(&(pJeu->personnage)) + 0.99f),
                                  (int)(personnageGetPosY(&(pJeu->personnage)) + 1)))
    {
        personnageSetSaut(&(pJeu->personnage), 1);
    }
    else
    {
        personnageSetSaut(&(pJeu->personnage), 0);
    }
    if(pJeu->personnage.saut==1)
        personnageSetAccelerationY(&pJeu->personnage, g);
}



void collisions(Jeu * pJeu)
{
    /* x et y, les position du personnage ( en haut a gauche )*/
    float x, y , xpos, ypos, ymax, xmax, yvalide, xvalide;
    float pas = 0.0;
    int test = 1 ,portail = 0;
    int i;
    float borneInf, borneSup;

    xvalide = personnageGetPosX(&(pJeu->personnage));
    yvalide = personnageGetPosY(&(pJeu->personnage));

    x = personnageGetPosX(&(pJeu->personnage));
    y = personnageGetPosY(&(pJeu->personnage));

    for(pas = 0; pas <=1 && test == 1 && portail == 0; pas+=0.01)
    {
        xpos = x + pas*IntervalleTemps*vectGetX(personnageGetVitesse(&pJeu->personnage));
        ypos = y + pas*IntervalleTemps*vectGetY(personnageGetVitesse(&pJeu->personnage));

        xmax = xpos + 0.99f;
        ymax = ypos + 0.99f;

        if((terrainPositionValide(&(pJeu->terrain) , (int)xpos, (int)ypos)) &&
                (terrainPositionValide(&(pJeu->terrain) , (int)xmax, (int)ypos)) &&
                (terrainPositionValide(&(pJeu->terrain) , (int)xmax, (int)ymax)) &&
                (terrainPositionValide(&(pJeu->terrain) , (int)xpos, (int)ymax)))
        {

            test=1;
            yvalide = ypos;
            xvalide = xpos;
        }
        else
        {
            test = 0;
        }
    }
    if(test)
        personnageDeplacement(&(pJeu->personnage));
    else
    {
        personnageSetX(&(pJeu->personnage), xvalide);
        personnageSetY(&(pJeu->personnage), yvalide);

        if(personnageGetSaut(&(pJeu->personnage)))
        {

            if(!(terrainPositionValide(&(pJeu->terrain) ,
                                       (int)personnageGetPosX(&(pJeu->personnage)),
                                       (int)(personnageGetPosY(&(pJeu->personnage)) - 1)))
                    ||
                    !(terrainPositionValide(&(pJeu->terrain) ,
                                            (int)(personnageGetPosX(&(pJeu->personnage))+ 0.99f),
                                            (int)(personnageGetPosY(&(pJeu->personnage)) - 1))))
            {
                 personnageSetAccelerationX(&pJeu->personnage, 0.0);

                 personnageSetVitesseY(&pJeu->personnage, 0.0 );
                 personnageSetVitesseX(&pJeu->personnage, 0.0);

            }
            else
            {
                personnageSetVitesseX(&pJeu->personnage, 0.0);
            }
        }
        else
        {
            personnageSetVitesseXY(&pJeu->personnage, 0.0, 0.0);
            personnageSetAccelerationXY(&pJeu->personnage, 0.0, 0.0);
        }
    }



    test=1;
    for(i=0; i<(pJeu->nbEnnemis); i++)
    {

        x = personnageGetPosX(&(pJeu->tabEnnemis[i].ennemi));
        y = personnageGetPosY(&(pJeu->tabEnnemis[i].ennemi));

        for(pas = 0; pas <=1 && test == 1; pas+=0.01)
        {


            xpos = x + pas*IntervalleTemps*vectGetX(&(pJeu->tabEnnemis[i].ennemi.vitesse));
            ypos = y + pas*IntervalleTemps*vectGetY(&(pJeu->tabEnnemis[i].ennemi.vitesse));

            xmax = xpos + 0.99f;
            ymax = ypos + 0.99f;

            if((terrainPositionValide(&(pJeu->terrain) , (int)xpos, (int)ypos)) &&
                    (terrainPositionValide(&(pJeu->terrain) , (int)xmax, (int)ypos)) &&
                    (terrainPositionValide(&(pJeu->terrain) , (int)xmax, (int)ymax)) &&
                    (terrainPositionValide(&(pJeu->terrain) , (int)xpos, (int)ymax)))
            {
                yvalide = ypos;
                xvalide = xpos;
                test=1;
            }
            else
            {
                test = 0;
            }
        }

        borneInf=ennemiGetXmin(&(pJeu->tabEnnemis[i]));
        borneSup=ennemiGetXmax(&(pJeu->tabEnnemis[i]));

        if (test)
        {
            if ( (xvalide>=borneSup) || (xvalide <= borneInf) )
            {
                ennemiChangeDeplacement(&(pJeu->tabEnnemis[i]));
            }
            else
            {
                ennemisDeplacement(pJeu,i);
            }
        }

        else /* ici différence car l'ennemi ne doit pas s'arrêter */
        {
            ennemiChangeDeplacement(&(pJeu->tabEnnemis[i]));
        }

    }
    /* Gestion des collisions entre le personnages et les ennemis */
}


void jeuPortailTeleportation(Jeu *pJeu)
{
    int xmax, ymax, xpos, ypos ;
    const Portail *portail1, *portail2;

    portail1 = jeuGetConstPortail(pJeu , 0);
    portail2 = jeuGetConstPortail(pJeu , 1);

    xpos = personnageGetPosX(&(pJeu->personnage));
    ypos = personnageGetPosY(&(pJeu->personnage));

    xmax = xpos + 1.00f;
    ymax = ypos + 1.00f;

    if(portailInteraction(portail1, (int)xpos , (int)ypos) ||
            portailInteraction(portail1, (int)xmax , (int)ypos) ||
            portailInteraction(portail1, (int)xmax ,  (int)ymax) ||
            portailInteraction(portail1, (int)xpos ,  (int)ymax) )
    {
        if(personnageGetTeleportation(&(pJeu->personnage)) == 0)
        {
            personnageSetX(&(pJeu->personnage), portailGetX(portail2));
            personnageSetY(&(pJeu->personnage),  portailGetY(portail2));
            personnageSetTeleportation(&(pJeu->personnage), 2);
        }

    }
    else if(portailInteraction(portail2, (int)xpos , (int)ypos) ||
            portailInteraction(portail2, (int)xmax , (int)ypos) ||
            portailInteraction(portail2, (int)xmax ,  (int)ymax) ||
            portailInteraction(portail2, (int)xpos ,  (int)ymax) )
    {
        if(personnageGetTeleportation(&(pJeu->personnage)) == 0)
        {
            personnageSetX(&(pJeu->personnage), portailGetX(portail1));
            personnageSetY(&(pJeu->personnage),  portailGetY(portail1));
            personnageSetTeleportation(&(pJeu->personnage), 1);
        }
    }

    else if(personnageGetTeleportation(&(pJeu->personnage)) == 2)
    {
         if(!portailInteraction(portail2, (int)xpos , (int)ypos) &&
            !portailInteraction(portail2, (int)xmax , (int)ypos) &&
            !portailInteraction(portail2, (int)xmax ,  (int)ymax) &&
            !portailInteraction(portail2, (int)xpos ,  (int)ymax) )
            {
                personnageSetTeleportation(&(pJeu->personnage), 0);
            }
    }
    else if(personnageGetTeleportation(&(pJeu->personnage)) == 1)
    {
         if(!portailInteraction(portail1, (int)xpos , (int)ypos) &&
            !portailInteraction(portail1, (int)xmax , (int)ypos) &&
            !portailInteraction(portail1, (int)xmax ,  (int)ymax) &&
            !portailInteraction(portail1, (int)xpos ,  (int)ymax) )
            {
                personnageSetTeleportation(&(pJeu->personnage), 0);
            }
    }
}
void jeuActionClavier(Jeu *pJeu,int  touche)
{

    switch(touche)
    {
    case 'g' :
        personnageGauche(&(pJeu->personnage));
        break; /* On va à gauche */

    case 'd' :
        personnageDroite(&(pJeu->personnage));
        break; /* On va à droite */

    case 's' :
        personnageSauter(&(pJeu->personnage));
        break; /* On saute */

    }
}

void ennemisDeplacement(const Jeu * pJeu, int i)
{

    int aleat;

    aleat = rand()%100;

    if(aleat==1)
    {
        ennemiChangeDeplacement(&(pJeu->tabEnnemis[i]));
    }
    else
    {
        /* p(t+1)=p(t)+ deltaT v(t) */
        personnageSetX( (&(pJeu->tabEnnemis[i].ennemi)) ,(personnageGetPosX(&(pJeu->tabEnnemis[i].ennemi))+IntervalleTemps*vectGetX(&(pJeu->tabEnnemis[i].ennemi.vitesse))));
        personnageSetY( (&(pJeu->tabEnnemis[i].ennemi)) ,(personnageGetPosY(&(pJeu->tabEnnemis[i].ennemi))+IntervalleTemps*vectGetY(&(pJeu->tabEnnemis[i].ennemi.vitesse))));

        if((vectGetX(&(pJeu->tabEnnemis[i].ennemi.vitesse)) > VitesseEnnemi))
            vectSetX(&(pJeu->tabEnnemis[i].ennemi.vitesse) ,VitesseEnnemi);

        if((vectGetX(&(pJeu->tabEnnemis[i].ennemi.vitesse)) < -VitesseEnnemi))
            vectSetX(&(pJeu->tabEnnemis[i].ennemi.vitesse) , -VitesseEnnemi);
    }

}

void jeuEvolue(Jeu *pJeu)
{
    jeuPersoGravite(pJeu);
    jeuPortailTeleportation(pJeu);
    collisions(pJeu);
}

